﻿using DllDependenciesAnalysis.Helpers;
using NuGet.Repositories;
using NuGet.Versioning;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DllDependenciesAnalysis.AnalysisPlans.Business
{
    public class PrintDllMissDependency : BaseAnalysisPlan
    {
        //public string NugetDir = "packages";

        public static Assembly LoadAssemblyByteFromFile(string file)
        {
            using (var fs = new FileStream(file, FileMode.Open))
            {
                var bytes = new byte[fs.Length];
                fs.Read(bytes, 0, bytes.Length);

                return Assembly.Load(bytes);
            }
        }

        public static List<AssemblyName> AnalysisAllMissDependency(string path, string[] searchPaths)
        {
            Console.WriteLine($"正在尝试处理 {path}");
            var files = Directory.GetFiles(path)
                ?.Where(n => IsProgramFile(n))
                .ToList();


            if (files?.Any() != true)
            {
                Console.WriteLine($"无法在目录中找到要处理的文件");
                return null;
            }

            var assemblies = files.Select(n => LoadAssemblyByteFromFile(n)).ToList();

            var allNames = new List<AssemblyName>();
            allNames.AddRange(assemblies.Select(n => n.GetName()));

            if (searchPaths?.Any() == true)
            {
                foreach (var searchItem in searchPaths)
                {
                    var tmp = Directory.GetFiles(searchItem)
                       ?.Where(n => IsProgramFile(n))
                       .ToList();


                    foreach (var itemFile in tmp)
                    {
                        try
                        {
                            var name = AssemblyName.GetAssemblyName(itemFile);
                            if (name != null)
                                allNames.Add(name);
                        }
                        catch (Exception ex)
                        {
                            //Console.WriteLine($"加载dll {itemFile} 时出错 {ex}");
                        }
                    }
                }
            }

            var missingNames = new List<AssemblyName>();
            var versionNotMatchNames = new List<AssemblyName>();

            foreach (var assembly in assemblies)
            {
                Console.WriteLine($"尝试解析 {assembly.FullName}");

                var needAssemblies = assembly.GetReferencedAssemblies();
                //Console.WriteLine($"共发现 {needAssemblies.Length} 个依赖");

                foreach (var needItem in needAssemblies)
                {
                    var matchAssemblies = allNames.Where(n => n.Name == needItem.Name).ToList();
                    if (matchAssemblies?.Any() != true)
                    {
                        using (new ConsoleColorContent(ConsoleColor.DarkYellow))
                        {
                            Console.WriteLine($"    依赖的 {needItem.FullName} 无法找到Dll");
                        }

                        missingNames.Add(needItem);
                    }
                    else
                    {
                        foreach (var matchItem in matchAssemblies)
                        {
                            if (matchItem.Version.GetLongHashCode() < needItem.Version.GetLongHashCode())
                            {
                                using (new ConsoleColorContent(ConsoleColor.DarkRed))
                                {
                                    Console.WriteLine($"    依赖的 {needItem.FullName} 版本{matchItem.Version} 小于需求值 {needItem.Version}");
                                }

                                versionNotMatchNames.Add(needItem);
                            }
                        }
                    }
                }
            }

            return missingNames.Union(versionNotMatchNames).ToList();


            //// 确认缺少的版本的内容
            //if (allErroNames?.Any() == true)
            //{
            //    // 尝试在本地还原内容
            //    var mappings = NugetHelper.Reduction(allErroNames);

            //    var localRepository = new NuGetv3LocalRepository(NugetDir);
            //    foreach (var item in mappings)
            //    {
            //        var packageInfo = localRepository.FindPackage(item.Key, new NuGetVersion(item.Value));
            //        if (packageInfo == null)
            //            continue;

            //        foreach (var packFile in packageInfo.Files)
            //        {
            //            Console.WriteLine(packFile);
            //        }
            //    }
            //}

            bool IsProgramFile(string file)
            {
                var suffixs = new[] { ".exe", ".dll" };
                return suffixs.Any(n => file.EndsWith(n, StringComparison.OrdinalIgnoreCase));
            }
        }

        public override void Analysis(AnalysisContent content)
        {
            AnalysisAllMissDependency(content.Path, content.SearchPaths?.ToArray());
        }
    }
}
